from django.db import transaction
from rest_framework import serializers
from goods.models import SKU, GoodsCategory, SPUSpecification, SpecificationOption, SKUSpecification
from celery_tasks.static_file.tasks import get_detail_html


class SKUSpecificationSerialzier(serializers.ModelSerializer):
    spec_id = serializers.IntegerField(write_only=True)
    option_id = serializers.IntegerField(write_only=True)

    class Meta:
        model = SKUSpecification
        fields = ('spec_id', 'option_id')


class SKUSerializer(serializers.ModelSerializer):
    """
    指定序列化器
    """
    spu_id = serializers.IntegerField()
    category_id = serializers.IntegerField()

    # 序列化返回时需要用到ｓｋｕ具体规格信息表数据
    specs = SKUSpecificationSerialzier(read_only=True)

    class Meta:
        model = SKU
        fields = "__all__"
        read_only_fields = ('spu', 'category')

    def create(self, validated_data):
        # 获取前端的数据specs
        specs = self.context['request'].data.get('specs')

        with transaction.atomic():
            # 开启事务
            # 设置保存点
            save_point = transaction.savepoint()
            try:
                # 保存ｓｋｕ表
                sku = SKU.objects.create(**validated_data)
                # 保存ｓｋｕ具体规格
                for spec in specs:
                    SKUSpecification.objects.create(spec_id=spec['spec_id'], option_id=spec['option_id'], sku=sku)
            except:
                # 事务回滚
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError('保存失败')
            else:
                transaction.savepoint_commit(save_point)

                return sku

    def update(self, instance, validated_data):
        # 获取前端的数据specs
        specs = self.context['request'].data.get('specs')

        with transaction.atomic():
            # 开启事务
            # 设置保存点
            save_point = transaction.savepoint()
            try:
                # 保存ｓｋｕ表
                sku = SKU.objects.filter(id=instance.id).update(**validated_data)
                # 保存ｓｋｕ具体规格
                for spec in specs:
                    SKUSpecification.objects.filter(sku=instance).update(**spec)
            except:
                # 事务回滚
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError('保存失败')
            else:
                # 静态化生成详情页面
                get_detail_html.delay(instance.id)
                transaction.savepoint_commit(save_point)

                return instance

class GoodsCategorySerializer(serializers.ModelSerializer):
    """
    分类序列化器
    """

    class Meta:
        model = GoodsCategory
        fields = "__all__"


class SpecificationOptionSerializer(serializers.ModelSerializer):
    """
    分类序列化器
    """

    class Meta:
        model = SpecificationOption
        fields = "__all__"


class SPUSpecificationSerializer(serializers.ModelSerializer):
    """
    商品规格序列化器
    """
    # 　嵌套返回　主表反映副表信息
    options = SpecificationOptionSerializer(many=True)

    class Meta:
        model = SPUSpecification
        fields = "__all__"
